Android 分区布局详解 您所在的位置:网站首页 etc fstab中有重复条目 Android 分区布局详解

Android 分区布局详解

2024-01-18 19:04| 来源: 网络整理| 查看: 265

在 Android 10 中,根文件系统已不再包含在 ramdisk.img 中,而是合并到了 system.img(即在创建 system.img 时始终将 BOARD_BUILD_SYSTEM_ROOT_IMAGE 视为已设置)。搭载 Android 10 的设备:

使用 system-as-root 分区布局(由编译流程自动执行,且不可选择更改这种行为)。必须使用 ramdisk,这对于 dm-linear 而言是必需的。必须将 BOARD_BUILD_SYSTEM_ROOT_IMAGE 设为 false。此设置仅用于区分使用 ramdisk 的设备和没有使用 ramdisk 的设备(这类设备直接装载 system.img)。

system-as-root 配置的含义在 Android 9 和 Android 10 之间有所不同。在 Android 9 system-as-root 配置中,BOARD_BUILD_SYSTEM_ROOT_IMAGE 设为 true,这会强制编译将根文件系统合并到 system.img 中,然后将 system.img 作为根文件系统 (rootfs) 进行装载。此配置对于搭载 Android 9 的设备是强制性的,但对于升级到 Android 9 及搭载较低 Android 版本的设备是可选的。在 Android 10 system-as-root 配置中,编译始终将 $TARGET_SYSTEM_OUT 和 $TARGET_ROOT_OUT 合并到 system.img 中;此配置是搭载 Android 10 的所有设备的默认行为。

Android 10 进行了进一步更改来支持动态分区,这是一种可以通过无线下载 (OTA) 更新来创建、销毁分区或调整分区大小的用户空间分区系统。作为此更改的一部分,Linux 内核无法再在搭载 Android 10 的设备上装载逻辑系统分区,因此该操作由第一阶段的 init 处理。

以下部分介绍了系统专用 OTA 的 system-as-root 要求,提供了有关将设备更新为使用 system-as-root 的指导(包括分区布局更改以及 dm-verity 内核要求),并详细介绍了 Android 10 中对 ramdisk 的更改。

关于系统专用 OTA

系统专用 OTA 需要 system-as-root 分区布局,可以让 Android 版本在不更改其他分区的情况下更新 system.img。搭载 Android 10 的所有设备都必须使用 system-as-root 分区布局来启用系统专用 OTA。

A/B 设备(将 system 分区作为 rootfs 进行装载)已经使用 system-as-root,不需要进行更改即可支持系统 OTA。非 A/B 设备(在 /system 装载 system 分区)必须更新为使用 system-as-root 分区布局才可支持系统 OTA。

如需详细了解 A/B 设备和非 A/B 设备,请参阅 A/B(无缝)系统更新。

更新为 system-as-root

要将非 A/B 设备更新为使用 system-as-root,您必须更新 boot.img 和 system.img 的分区架构、设置 dm-verity,并移除特定于设备的根文件夹中的任何启动依赖项。

更新分区

不同于将 /boot 改为 recovery 分区的 A/B 设备,非 A/B 设备必须保留单独的 /recovery 分区,因为它们没有后备插槽分区(例如从 boot_a 到 boot_b)。如果在非 A/B 设备上移除 /recovery 并使其与 A/B 架构类似,那么在 /boot 分区更新失败时,恢复模式可能无法正常工作。因此,在非 A/B 设备上,必须将 /recovery 分区与 /boot 分区分开,这意味着将继续延迟更新恢复映像(即和搭载 Android 9 之前版本的设备一样)。

下表列出了非 A/B 设备在使用 Android 9 前后的映像分区差异。

映像ramdisk(Android 9 之前)system-as-root(Android 9 之后)boot.img包含内核和 ramdisk.img: ramdisk.img -/ - init.rc - init - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... 仅包含正常启动内核。recovery.img包含恢复内核和恢复 ramdisk.img。system.img包含以下内容: system.img -/ - bin/ - etc - vendor -> /vendor - ... 包含原始 system.img 和 ramdisk.img 的合并内容: system.img -/ - init.rc - init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ...

分区本身不会更改;ramdisk 和 system-as-root 都使用以下分区架构:

/boot/system/recovery/vendor 等 设置 dm-verity

在 system-as-root 中,内核必须使用 dm-verity 在 /(装载点)下装载 system.img。AOSP 支持 system.img 的下列 dm-verity 实现。

vboot 1.0

对于 vboot 1.0,内核必须在 /system 上解析 Android 专用元数据,然后转换为 dm-verity 参数以设置 dm-verity(需要这些内核补丁程序)。下面的示例显示了内核命令行中 system-as-root 的 dm-verity 相关设置:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="system none ro,0 1 android-verity /dev/sda34" veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

对于 vboot 2.0 (AVB),引导加载程序必须先整合 external/avb/libavb,然后 external/avb/libavb 会解析 /system 的哈希树描述符,再将解析结果转换为 dm-verity 参数,最后通过内核命令行将这些参数传递给内核。(/system 的哈希树描述符可能位于 /vbmeta 或 /system 本身上)。

vboot 2.0 需要以下内核补丁程序:

https://android-review.googlesource.com/#/c/kernel/common/+/158491/内核 4.4 补丁程序、内核 4.9 补丁程序等

注意:您也可以在 external/avb/contrib/linux/ 查找 AVB 专用内核补丁程序文件。

下面的示例显示了内核命令行中 system-as-root 的 dm-verity 相关设置:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="1 vroot none ro 1,0 5159992 verity 1 PARTUUID=00000016-0000-0000-0000-000000000000 PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999 sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2 8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption ignore_zero_blocks use_fec_from_device PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks 650080 fec_start 650080" 使用特定于设备的根文件夹

使用 system-as-root 时,在设备上刷写常规系统映像 (GSI) 之后(以及在运行供应商测试套件测试之前),任何通过 BOARD_ROOT_EXTRA_FOLDERS 添加的特定于设备的根文件夹都会消失,因为整个根目录内容已被 system-as-root GSI 取代。如果对特定于设备的根文件夹有依赖性(例如将此类文件夹用作装载点),则移除这些文件夹可能会导致设备无法启动。

为避免此问题,请勿使用 BOARD_ROOT_EXTRA_FOLDERS 来添加特定于设备的根文件夹。如果需要指定特定于设备的装载点,请使用 /mnt/vendor/(已添加到这些更改列表中)。这些特定于供应商的装载点可在 fstab 设备树(适用于第一阶段的装载)和 /vendor/etc/fstab.{ro.hardware} 文件中直接指定,而无需进行额外设置(因为 fs_mgr 将在 /mnt/vendor/* 下自动创建它们)。

Ramdisk

在 Android 10 中,第一阶段 ramdisk 包含第一阶段 init 二进制文件(按照 fstab 条目的指定执行早期装载)和供应商 fstab 文件。(与在 Android 9 中一样,system.img 包含 $TARGET_ROOT_OUT 的内容。)

对于具有 boot-ramdisk 的设备(非 A/B),第一阶段 init 是位于 /init 的静态可执行文件。这些设备将 system.img 作为 /system 进行装载,然后执行切换根操作将装载从 /system 移动到 /。装载完成后,ramdisk 的内容将会释放。对于将恢复用作 ramdisk 的设备,第一阶段 init 位于恢复 ramdisk 中的 /init。这些设备首先将根切换到 /first_stage_ramdisk,以便从环境中移除恢复组件,然后执行与具有 boot-ramdisk 的设备一样的操作(即,将 system.img 作为 /system 进行装载,切换根以将该装载移动到 /,然后在装载完成后释放 ramdisk 内容)。如果内核命令行中存在 androidboot.force_normal_boot=1,则设备会正常启动(启动到 Android)而不是启动到恢复模式。

在第一阶段 init 完成后,它会使用 selinux_setup 参数执行 /system/bin/init,以便编译 SELinux 并将其加载到系统中。最后,init 会使用 second_stage 参数再次执行 /system/bin/init。此时,init 的主要阶段将会运行,并使用 init.rc 脚本继续执行启动过程。

注意:Android 10 将 ramdisk 内容替换为第一阶段 init 可执行文件,后者与以前的 ramdisk 启动系统的方式不兼容。

分区布局(非 A/B 设备)

下面的部分详细介绍了非 A/B 设备在使用 Android 10 前后的分区布局差异。

boot.img

Ramdisk(Android 8.x 及更低版本)System as root(Android 9)Ramdisk(Android 10)包含内核和 ramdisk.img。   ramdisk.img -/ - init.rc - init - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... 仅包含正常启动内核。包含内核和 ramdisk.img。   ramdisk.img -/ - init - vendor fstab files - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ...

recovery.img

Ramdisk(Android 8.x 及更低版本)System as root(Android 9)Ramdisk(Android 10)包含恢复内核和恢复 ramdisk.img。

system.img

Ramdisk(Android 8.x 及更低版本)System as root(Android 9)Ramdisk(Android 10)包含 system.img。   system.img -/ - bin/ - etc - vendor -> /vendor - ... 包含 $TARGET_SYSTEM_OUT 和 $TARGET_ROOT_OUT 的合并内容。   system.img -/ - init.rc - init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... 包含 $TARGET_SYSTEM_OUT 和 $TARGET_ROOT_OUT 的合并内容。   system.img -/ - init.rc - init -> /system/bin/init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... 分区布局(A/B 设备)

下面的部分详细介绍了 A/B 设备在使用 Android 10 前后的分区布局差异。

boot.img

System as root(Android 9)Ramdisk(Android 10)包含正常启动内核和 recovery-ramdisk (BOARD_USES_RECOVERY_AS_BOOT := true)。 Recovery-ramdisk 仅用于启动到恢复模式。包含正常启动内核和 recovery-ramdisk (BOARD_USES_RECOVERY_AS_BOOT := true)。 Recovery-ramdisk 用于启动到恢复模式和 Android。 ramdisk.img -/ - init -> /system/bin/init - first_stage_ramdisk - vendor fstab files - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ...

system.img

System as root(Android 9)Ramdisk(Android 10)包含 $TARGET_SYSTEM_OUT 和 $TARGET_ROOT_OUT 的合并内容。   system.img -/ - init.rc - init -> /system/bin/init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... 提前装载分区

支持 Treble 的设备必须启用第一阶段装载,以确保 init 可以加载分布在 system 和 vendor 分区的安全增强型 (SELinux) 政策 Fragment。此访问权限还可实现在内核启动后尽快加载内核模块。

如需执行提前装载,Android 必须有权访问模块所在的文件系统。Android 8.0 及更高版本支持在 init 的第一阶段(即初始化 SElinux 之前)装载 /system、/vendor 或 /odm。

AOSP 提前装载更改摘要:

提前装载 v1 和 v2杂项分区查找移除提前装载支持使用 VBoot 2.0 (AVB) 完成提前装载Fstab 条目

在 Android 9 及更低版本中,设备可以使用设备树叠加层 (DTO) 为提前装载的分区指定 fstab 条目。在 Android 10 及更高版本中,设备必须使用第一阶段 ramdisk 中的 fstab 文件为提前装载的分区指定 fstab 条目。Android 10 引入了以下可在 fstab 文件中使用的 fs_mgr 标记:

first_stage_mount 表明将由第一阶段 init 装载分区。logical 表明这是一个动态分区。avb=vbmeta-partition-name 可指定 vbmeta 分区。第一阶段 init 可初始化该分区,然后再装载其他分区。如果该条目的 vbmeta 分区已由上一行中的其他 fstab 条目指定,可以省略此标记的参数。

以下示例展示了将 system、vendor 和 product 分区设置为逻辑(动态)分区的 fstab 条目。

#     system   /system     ext4    ro,barrier=1     wait,slotselect,avb=vbmeta_system,logical,first_stage_mount vendor   /vendor     ext4    ro,barrier=1     wait,slotselect,avb=vbmeta,logical,first_stage_mount product  /product    ext4    ro,barrier=1     wait,slotselect,avb,logical,first_stage_mount

在上述示例中,供应商使用 fs_mgr 标记 avb=vbmeta 指定了 vbmeta 分区,但 product 省略了 vbmeta 参数,因为供应商已将 vbmeta 添加到了分区列表。

搭载 Android 10 及更高版本的设备必须将 fstab 文件放在 ramdisk 和 vendor 分区中。

Ramdisk

ramdisk通过直面意思就大概能理解意思,ram disk虚拟内存盘,将ram模拟成硬盘来使用的文件系统。对于传统的磁盘文件系统来说,这样做的好处是可以极大提高文件访问速度;但由于是ram,所以在掉电后,这部分内容不能保存。ramdisk文件系统是在系统上电后直接从磁盘一次性加载到内存,在整个运行期间都不会有写回操作,所以,任何修改都掉电后丢失。如下图所示:

fstab 文件在 ramdisk 中的位置取决于设备如何使用 ramdisk。

具有启动 ramdisk 的设备必须将 fstab 文件放在启动 ramdisk 根目录中。如果设备同时具有启动 ramdisk 和恢复 ramdisk,就无需对恢复 ramdisk 进行任何更改。示例:

PRODUCT_COPY_FILES +=  device/google//fstab.hardware:$(TARGET_COPY_OUT_RAMDISK)/fstab.$(PRODUCT_PLATFORM)

将恢复用作 ramdisk 的设备必须使用内核命令行参数 androidboot.force_normal_boot=1 来决定是启动到 Android 还是继续启动到恢复模式。在这些设备中,第一阶段 init 在装载提前装载分区之前将根操作切换到了 /first_stage_ramdisk,因此设备必须将 fstab 文件放在 $(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk 中。示例:

PRODUCT_COPY_FILES +=  device/google//fstab.hardware:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) Vendor

所有设备都必须将 fstab 文件的副本放到 /vendor/etc 中。这是因为第一阶段 init 在完成分区提前装载之后释放了 ramdisk,并执行了切换根操作,以将位于 /system 的装载移动到了 /。因此,后续任何需要访问 fstab 文件的操作都必须使用 /vendor/etc 中的副本。示例:

PRODUCT_COPY_FILES +=  device/google//fstab.hardware:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(PRODUCT_PLATFORM) 提前装载分区,VBoot 1.0

使用 VBoot 1.0 提前装载分区的要求包括:

设备节点路径必须在 fstab 和设备树条目中使用其 by-name 符号链接。例如,确保对分区进行命名且设备节点为 /dev/block/…./by-name/{system,vendor,odm},而不是使用 /dev/block/mmcblk0pX 指定分区。在产品的设备配置中(即 device/oem/project/device.mk 中)为 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION 和 CUSTOM_IMAGE_VERITY_BLOCK_DEVICE 指定的路径必须与 fstab/设备树条目中相应块设备节点指定的 by-name 相匹配。示例: PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/…./by-name/system PRODUCT_VENDOR_VERITY_PARTITION := /dev/block/…./by-name/vendor CUSTOM_IMAGE_VERITY_BLOCK_DEVICE := /dev/block/…./by-name/odm 通过设备树叠加层提供的条目不得在 fstab 文件 Fragment 中出现重复。例如,指定某个条目以在设备树中装载 /vendor 时,fstab 文件不得重复该条目。不得提前装载需要 verifyatboot 的分区(此操作不受支持)。必须在 kernel_cmdline 中使用 androidboot.veritymode 选项指定验证分区的真实模式/状态(现有要求)。提前装载设备树,VBoot 1.0

在 Android 8.x 及更高版本中,init 会解析设备树并创建 fstab 条目,以在其第一阶段提前装载分区。fstab 条目采用以下形式:

src mnt_point type mnt_flags fs_mgr_flags

定义设备树属性以模拟该格式:

fstab 条目必须在设备树中的 /firmware/android/fstab 下,且必须将兼容字符串设置为 android,fstab。/firmware/android/fstab 下的每个节点都被视为单个提前装载 fstab 条目。节点必须定义以下属性: dev 必须指向表示 by-name 分区的设备节点type 必须是文件系统类型(如在 fstab 文件中一样)mnt_flags 必须是装载标记的逗号分隔列表(如在 fstab 文件中一样)fsmgr_flags 必须是 Android fs_mgr flags 列表(如在 fstab 文件中一样)A/B 分区必须具有 slotselect fs_mgr 选项。已启用 dm-verity 的分区必须具有 verify fs_mgr 选项。示例:N6P 上的 /system 和 /vendor

下面的示例显示的是在 Nexus 6P 上为 system 和 vendor 分区提前装载设备树:

/ {   firmware {     android {       compatible = "android,firmware";   fstab {     compatible = "android,fstab";     system {       compatible = "android,system";       dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/system";       type = "ext4";       mnt_flags = "ro,barrier=1,inode_readahead_blks=8";       fsmgr_flags = "wait,verify";     };     vendor {       compatible = "android,vendor";       dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";       type = "ext4";       mnt_flags = "ro,barrier=1,inode_readahead_blks=8";       fsmgr_flags = "wait";     };       };     };   }; }; 示例:Pixel 上的 /vendor

下面的示例显示的是在 Pixel 上为 /vendor 提前装载设备树(请务必为 A/B 分区添加 slotselect):

/ {   firmware {     android {       compatible = "android,firmware";       fstab {         compatible = "android,fstab";         vendor {           compatible = "android,vendor";           dev = "/dev/block/platform/soc/624000.ufshc/by-name/vendor";           type = "ext4";           mnt_flags = "ro,barrier=1,discard";           fsmgr_flags = "wait,slotselect,verify";         };       };     };   }; }; 提前装载分区,VBoot 2.0

VBoot 2.0 是 Android 启动时验证 (AVB)。使用 VBoot 2.0 提前装载分区的要求如下:

设备节点路径必须在 fstab 和设备树条目中使用其 by-name 符号链接。例如,确保对分区进行命名且设备节点为 /dev/block/…./by-name/{system,vendor,odm},而不是使用 /dev/block/mmcblk0pX 指定分区。VBoot 1.0 所用的构建系统变量(如 PRODUCT_{SYSTEM,VENDOR}_VERITY_PARTITION 和 CUSTOM_IMAGE_VERITY_BLOCK_DEVICE)对 VBoot 2.0 而言并不是必需的。您应定义 VBoot 2.0 中引入的构建变量(包括 BOARD_AVB_ENABLE := true);如需查看完整配置,请参阅适用于 AVB 的构建系统集成。通过设备树叠加层提供的条目不得在 fstab 文件 Fragment 中出现重复。例如,如果您指定某个条目以在设备树中装载 /vendor,fstab 文件不得重复该条目。VBoot 2.0 不支持 verifyatboot,无论是否启用了提前装载。必须在 kernel_cmdline 中使用 androidboot.veritymode 选项指定验证分区的真实模式/状态(现有要求)。确保包含以下 AVB 修复程序: https://android-review.googlesource.com/#/q/topic:libavb-api-rev-for-verity-modes+(status:open+OR+status:merged)https://android-review.googlesource.com/#/c/394215/提前装载设备树,VBoot 2.0

VBoot 2.0 设备树中的配置与 VBoot 1.0 中的大致相同,但还有以下几项不同之处:

fsmgr_flag 由 verify 变为 avb。包含 AVB 元数据的所有分区都必须位于设备树的 VBMeta 条目中,即使相应的分区并非提前装载的分区(如 /boot)也是如此。示例:N5X 上的 /system 和 /vendor

下面的示例显示的是在 Nexus 5X 上为 system 和 vendor 分区提前装载设备树。注意:

/system 使用 AVB 进行装载,且 /vendor 的装载不需要进行完整性验证。由于 Nexus 5X 没有 /vbmeta 分区,因此顶层 vbmeta 位于 /boot 分区的末端(如需了解详情,请参阅 AOSP 变更列表)。 / {   firmware {     android {       compatible = "android,firmware";       vbmeta {       compatible = "android,vbmeta";       parts = "boot,system,vendor";       };   fstab {     compatible = "android,fstab";     system {       compatible = "android,system";       dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/system";       type = "ext4";       mnt_flags = "ro,barrier=1,inode_readahead_blks=8";       fsmgr_flags = "wait,avb";         };     vendor {       compatible = "android,vendor";       dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor";       type = "ext4";       mnt_flags = "ro,barrier=1,inode_readahead_blks=8";       fsmgr_flags = "wait";         };       };     };   }; }; 示例:Pixel 上的 /vendor

下面的示例显示的是在 Pixel 上提前装载 /vendor。注意:

很多分区都是在 vbmeta 条目中指定的,因为这些分区受 AVB 保护。请务必包含所有 AVB 分区,即使仅提前装载了 /vendor 也是如此。请务必为 A/B 分区添加 slotselect。/ {   vbmeta {       compatible = "android,vbmeta";   parts = "vbmeta,boot,system,vendor,dtbo";   };   firmware {     android {       compatible = "android,firmware";       fstab {         compatible = "android,fstab";         vendor {           compatible = "android,vendor";           dev = "/dev/block/platform/soc/624000.ufshc/by-name/vendor";           type = "ext4";           mnt_flags = "ro,barrier=1,discard";           fsmgr_flags = "wait,slotselect,avb";         };       };     };   }; };


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有